# budget_page.py
import tkinter as tk
from tkinter import ttk, messagebox
import datetime
from categories import EXPENSE_CATEGORIES
from ui.base import UIBase

class BudgetPage(UIBase):
    def __init__(self, parent, db, analysis=None):
        super().__init__(parent, db, analysis)
        self.parent = parent
        self.templates = {
            "学生预算": {
                "食品酒水": 800, "交通出行": 200, "衣服饰品": 300, 
                "学习进修": 500, "休闲娱乐": 200, "其他支出": 100
            },
            "上班族预算": {
                "食品酒水": 1500, "交通出行": 500, "衣服饰品": 800,
                "居家物业": 2000, "休闲娱乐": 500, "学习进修": 300
            },
            "家庭预算": {
                "食品酒水": 2500, "交通出行": 800, "衣服饰品": 1000,
                "居家物业": 3000, "学习进修": 600, "医疗保健": 500,
                "人情往来": 300, "其他支出": 200
            }
        }
        self.frame = ttk.Frame(parent)
        self.create_budget_tab()
        
    def create_budget_tab(self):
        """创建预算管理标签页"""
        # 创建预算管理的子标签页
        self.budget_notebook = ttk.Notebook(self.frame)
        self.budget_notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 基本预算设置页面
        self.basic_budget_frame = ttk.Frame(self.budget_notebook)
        self.budget_notebook.add(self.basic_budget_frame, text="预算设置")
        
        # 预算预警页面
        self.alert_budget_frame = ttk.Frame(self.budget_notebook)
        self.budget_notebook.add(self.alert_budget_frame, text="预算预警")
        
        # 预算趋势分析页面
        self.trend_budget_frame = ttk.Frame(self.budget_notebook)
        self.budget_notebook.add(self.trend_budget_frame, text="趋势分析")
        
        # 初始化预算子页面
        self.create_basic_budget_tab()
        self.create_alert_budget_tab()
        self.create_trend_budget_tab()

    def create_basic_budget_tab(self):
        """创建基本预算设置页面"""
        # 预算模板功能
        template_frame = ttk.LabelFrame(self.basic_budget_frame, text="预算模板", padding=10)
        template_frame.pack(fill=tk.X, padx=10, pady=5)
        
        # 模板选择
        template_select_frame = ttk.Frame(template_frame)
        template_select_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(template_select_frame, text="快速设置:").pack(side=tk.LEFT)
        self.template_var = tk.StringVar(value="选择模板")
        template_combo = ttk.Combobox(template_select_frame, textvariable=self.template_var, 
                                    state="readonly", width=15)
        
        template_combo['values'] = list(self.templates.keys())
        template_combo.pack(side=tk.LEFT, padx=5)
        
        ttk.Button(template_select_frame, text="应用模板", 
                command=self.apply_budget_template).pack(side=tk.LEFT, padx=5)
        
        # 自定义模板保存
        template_save_frame = ttk.Frame(template_frame)
        template_save_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(template_save_frame, text="模板名称:").pack(side=tk.LEFT)
        self.custom_template_name = tk.StringVar()
        ttk.Entry(template_save_frame, textvariable=self.custom_template_name, width=15).pack(side=tk.LEFT, padx=5)
        
        ttk.Button(template_save_frame, text="保存为模板", 
                command=self.save_current_as_template).pack(side=tk.LEFT, padx=5)
        
        # 原有的预算设置功能
        setting_frame = ttk.LabelFrame(self.basic_budget_frame, text="预算设置", padding=10)
        setting_frame.pack(fill=tk.X, padx=10, pady=5)
        
        # 分类选择
        category_frame = ttk.Frame(setting_frame)
        category_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(category_frame, text="支出分类:").pack(side=tk.LEFT)
        self.budget_category = tk.StringVar()
        budget_category_combo = ttk.Combobox(category_frame, textvariable=self.budget_category, state="readonly")
        budget_category_combo['values'] = list(EXPENSE_CATEGORIES.keys())
        budget_category_combo.pack(side=tk.LEFT, padx=5)
        
        # 金额输入
        amount_frame = ttk.Frame(setting_frame)
        amount_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(amount_frame, text="预算金额:").pack(side=tk.LEFT)
        self.budget_amount = tk.StringVar()
        ttk.Entry(amount_frame, textvariable=self.budget_amount, width=15).pack(side=tk.LEFT, padx=5)
        ttk.Label(amount_frame, text="元/月").pack(side=tk.LEFT)
        
        # 按钮
        button_frame = ttk.Frame(setting_frame)
        button_frame.pack(fill=tk.X, pady=5)
        
        ttk.Button(button_frame, text="设置预算", command=self.set_budget).pack(side=tk.LEFT)
        ttk.Button(button_frame, text="刷新", command=self.refresh_budgets).pack(side=tk.LEFT, padx=5)
        
        # 预算列表
        list_frame = ttk.LabelFrame(self.basic_budget_frame, text="当前预算", padding=10)
        list_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 创建树形视图
        columns = ("分类", "预算金额", "实际支出", "剩余预算", "使用率")
        self.budget_tree = ttk.Treeview(list_frame, columns=columns, show="headings")
        
        # 设置列标题
        for col in columns:
            self.budget_tree.heading(col, text=col)
            self.budget_tree.column(col, width=120)
        
        # 滚动条
        scrollbar = ttk.Scrollbar(list_frame, orient=tk.VERTICAL, command=self.budget_tree.yview)
        self.budget_tree.configure(yscrollcommand=scrollbar.set)
        
        self.budget_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 初始加载预算数据
        self.refresh_budgets()

    def create_alert_budget_tab(self):
        """创建预算预警页面"""
        # 预警设置
        alert_frame = ttk.LabelFrame(self.alert_budget_frame, text="预警设置", padding=10)
        alert_frame.pack(fill=tk.X, padx=10, pady=5)
        
        # 预警阈值设置
        threshold_frame = ttk.Frame(alert_frame)
        threshold_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(threshold_frame, text="预警阈值:").pack(side=tk.LEFT)
        self.alert_threshold = tk.StringVar(value="80")
        threshold_spinbox = ttk.Spinbox(threshold_frame, from_=50, to=100, width=5, 
                                    textvariable=self.alert_threshold)
        threshold_spinbox.pack(side=tk.LEFT, padx=5)
        ttk.Label(threshold_frame, text="% (当预算使用率达到此百分比时预警)").pack(side=tk.LEFT)
        
        # 按钮框架
        alert_button_frame = ttk.Frame(alert_frame)
        alert_button_frame.pack(fill=tk.X, pady=5)
        
        ttk.Button(alert_button_frame, text="启用预警", command=self.enable_budget_alerts).pack(side=tk.LEFT)
        ttk.Button(alert_button_frame, text="立即检查", command=self.check_budget_alerts).pack(side=tk.LEFT, padx=5)
        ttk.Button(alert_button_frame, text="关闭预警", command=self.disable_budget_alerts).pack(side=tk.LEFT, padx=5)
        
        # 预警状态显示
        self.alert_status = ttk.Label(alert_frame, text="预警功能状态: 未设置", foreground="gray")
        self.alert_status.pack(pady=5)
        
        # 预警历史
        history_frame = ttk.LabelFrame(self.alert_budget_frame, text="预警历史", padding=10)
        history_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 创建预警历史表格
        columns = ("时间", "分类", "使用率", "预警信息")
        self.alert_history_tree = ttk.Treeview(history_frame, columns=columns, show="headings")
        
        for col in columns:
            self.alert_history_tree.heading(col, text=col)
            self.alert_history_tree.column(col, width=120)
        
        scrollbar = ttk.Scrollbar(history_frame, orient=tk.VERTICAL, command=self.alert_history_tree.yview)
        self.alert_history_tree.configure(yscrollcommand=scrollbar.set)
        
        self.alert_history_tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 加载预警设置
        self.load_alert_settings()

    def create_trend_budget_tab(self):
        """创建预算趋势分析页面"""
        # 趋势分析设置
        trend_setting_frame = ttk.LabelFrame(self.trend_budget_frame, text="趋势分析设置", padding=10)
        trend_setting_frame.pack(fill=tk.X, padx=10, pady=5)
        
        # 选择要查看的分类
        trend_category_frame = ttk.Frame(trend_setting_frame)
        trend_category_frame.pack(fill=tk.X, pady=5)
        
        ttk.Label(trend_category_frame, text="查看分类:").pack(side=tk.LEFT)
        self.trend_category = tk.StringVar()
        trend_category_combo = ttk.Combobox(trend_category_frame, textvariable=self.trend_category, 
                                        state="readonly", width=15)
        trend_category_combo['values'] = list(EXPENSE_CATEGORIES.keys())
        trend_category_combo.pack(side=tk.LEFT, padx=5)
        
        ttk.Label(trend_category_frame, text="分析月份数:").pack(side=tk.LEFT, padx=(20,0))
        self.trend_months = tk.StringVar(value="6")
        months_combo = ttk.Combobox(trend_category_frame, textvariable=self.trend_months, 
                                width=5, state="readonly")
        months_combo['values'] = ["3", "6", "12"]
        months_combo.pack(side=tk.LEFT, padx=5)
        
        ttk.Button(trend_category_frame, text="生成趋势图", 
                command=self.show_budget_trend).pack(side=tk.LEFT, padx=10)
        
        # 趋势图显示区域
        self.trend_chart_frame = ttk.Frame(self.trend_budget_frame)
        self.trend_chart_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)

    def load_alert_settings(self):
        """加载预警设置"""
        alert_settings = self.db.get_budget_alert()
        self.alert_threshold.set(str(alert_settings['threshold']))
        
        if alert_settings.get('is_enabled', False):
            self.alert_status.config(text=f"预警功能已启用 (阈值: {alert_settings['threshold']}%)", foreground="green")
        else:
            self.alert_status.config(text="预警功能已关闭", foreground="gray")

    def enable_budget_alerts(self):
        """启用预算预警"""
        try:
            threshold = int(self.alert_threshold.get())
            if threshold < 50 or threshold > 100:
                messagebox.showerror("错误", "预警阈值必须在50%-100%之间")
                return
            
            self.db.set_budget_alert(threshold)
            self.alert_status.config(text=f"预警功能已启用 (阈值: {threshold}%)", foreground="green")
            messagebox.showinfo("成功", "预算预警功能已启用")
            
        except ValueError:
            messagebox.showerror("错误", "请输入有效的阈值")

    def disable_budget_alerts(self):
        """禁用预算预警"""
        # 这里需要更新数据库，将is_enabled设置为False
        self.alert_status.config(text="预警功能已关闭", foreground="gray")
        messagebox.showinfo("成功", "预算预警功能已关闭")

    def check_budget_alerts(self):
        """检查预算预警"""
        now = datetime.datetime.now()
        year = now.year
        month = now.month
        
        budget_status = self.db.get_budget_status(year, month)
        threshold = int(self.alert_threshold.get())
        
        alerts = []
        for status in budget_status:
            if status['budget'] > 0 and status['usage_rate'] >= threshold:
                alerts.append({
                    'category': status['category'],
                    'usage_rate': status['usage_rate'],
                    'message': f"{status['category']} 已使用 {status['usage_rate']:.1f}%"
                })
        
        if alerts:
            self.show_alert_message(alerts)
        else:
            messagebox.showinfo("预算检查", "所有分类预算使用情况正常")

    def show_alert_message(self, alerts):
        """显示预警消息"""
        alert_window = tk.Toplevel(self.parent)
        alert_window.title("预算预警")
        alert_window.geometry("400x300")
        
        # 设置窗口位置（居中）
        alert_window.transient(self.parent)
        alert_window.grab_set()
        
        ttk.Label(alert_window, text="💡 预算预警", font=("Arial", 12, "bold")).pack(pady=10)
        
        # 创建文本框显示预警信息
        text_frame = ttk.Frame(alert_window)
        text_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        text_widget = tk.Text(text_frame, wrap=tk.WORD, width=50, height=10)
        scrollbar = ttk.Scrollbar(text_frame, orient=tk.VERTICAL, command=text_widget.yview)
        text_widget.configure(yscrollcommand=scrollbar.set)
        
        text_widget.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 添加预警信息
        alert_text = "以下分类已超过预警阈值：\n\n"
        for alert in alerts:
            alert_text += f"• {alert['message']}\n"
            # 同时添加到预警历史
            self.add_alert_to_history(alert['category'], alert['usage_rate'])
        
        alert_text += "\n建议适当控制相关支出。"
        
        text_widget.insert(tk.END, alert_text)
        text_widget.config(state=tk.DISABLED)
        
        ttk.Button(alert_window, text="确定", command=alert_window.destroy).pack(pady=10)

    def add_alert_to_history(self, category: str, usage_rate: float):
        """添加预警到历史记录"""
        now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
        
        # 添加到预警历史表格
        self.alert_history_tree.insert("", "end", values=(
            now,
            category,
            f"{usage_rate:.1f}%",
            "超过预警阈值"
        ))

    def show_budget_trend(self):
        """显示预算执行趋势"""
        # 清空现有图表
        for widget in self.trend_chart_frame.winfo_children():
            widget.destroy()
        
        category = self.trend_category.get()
        months = int(self.trend_months.get())
        
        if not category:
            ttk.Label(self.trend_chart_frame, text="请选择要查看的分类").pack(pady=20)
            return
        
        # 获取历史预算执行数据
        trend_data = self.get_budget_trend_data(category, months)
        
        if not trend_data:
            ttk.Label(self.trend_chart_frame, text="暂无足够的历史数据").pack(pady=20)
            return
        
        # 绘制趋势图
        self.plot_budget_trend(trend_data, category)

    def get_budget_trend_data(self, category: str, months: int) -> list:
        """获取预算执行趋势数据"""
        trend_data = []
        now = datetime.datetime.now()
        
        for i in range(months):
            # 计算要查询的年份和月份
            year = now.year
            month = now.month - i
            
            # 处理跨年
            while month <= 0:
                year -= 1
                month += 12
            
            # 获取该月份的预算状态
            budget_status = self.db.get_budget_status(year, month)
            for status in budget_status:
                if status['category'] == category:
                    trend_data.append({
                        'period': f"{year}-{month:02d}",
                        'budget': status['budget'],
                        'actual': status['actual'],
                        'usage_rate': status['usage_rate']
                    })
                    break
            else:
                # 如果该月份没有找到该分类的预算，添加空数据
                trend_data.append({
                    'period': f"{year}-{month:02d}",
                    'budget': 0,
                    'actual': 0,
                    'usage_rate': 0
                })
        
        return trend_data[::-1]  # 反转，使时间正序

    def plot_budget_trend(self, trend_data: list, category: str):
        """绘制预算执行趋势图"""
        try:
            import matplotlib.pyplot as plt
            from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
            
            periods = [data['period'] for data in trend_data]
            budgets = [data['budget'] for data in trend_data]
            actuals = [data['actual'] for data in trend_data]
            usage_rates = [data['usage_rate'] for data in trend_data]
            
            # 创建图表
            fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8))
            
            # 设置中文字体
            plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei']
            plt.rcParams['axes.unicode_minus'] = False
            
            # 金额趋势图
            x = range(len(periods))
            width = 0.35
            
            bars1 = ax1.bar([i - width/2 for i in x], budgets, width, label='预算', alpha=0.7, color='lightblue')
            bars2 = ax1.bar([i + width/2 for i in x], actuals, width, label='实际支出', alpha=0.7, color='lightcoral')
            ax1.set_ylabel('金额 (元)')
            ax1.set_title(f'{category} - 预算执行趋势')
            ax1.legend()
            ax1.set_xticks(x)
            ax1.set_xticklabels(periods, rotation=45)
            
            # 在柱状图上显示数值
            for i, (budget, actual) in enumerate(zip(budgets, actuals)):
                if budget > 0:
                    ax1.text(i - width/2, budget + max(budgets)/50, f'{budget:.0f}', 
                            ha='center', va='bottom', fontsize=8)
                if actual > 0:
                    ax1.text(i + width/2, actual + max(actuals)/50, f'{actual:.0f}', 
                            ha='center', va='bottom', fontsize=8)
            
            # 使用率趋势图
            colors = ['green' if rate < 80 else 'orange' if rate < 100 else 'red' for rate in usage_rates]
            
            bars = ax2.bar(x, usage_rates, color=colors, alpha=0.7)
            ax2.set_ylabel('使用率 (%)')
            ax2.set_xlabel('月份')
            ax2.set_xticks(x)
            ax2.set_xticklabels(periods, rotation=45)
            
            # 在柱子上显示百分比
            for bar, rate in zip(bars, usage_rates):
                height = bar.get_height()
                if height > 0:  # 只在有数据时显示
                    ax2.text(bar.get_x() + bar.get_width()/2., height + 1,
                            f'{rate:.1f}%', ha='center', va='bottom', fontsize=9)
            
            # 添加参考线
            ax2.axhline(y=80, color='orange', linestyle='--', alpha=0.5, label='预警线 (80%)')
            ax2.axhline(y=100, color='red', linestyle='--', alpha=0.5, label='预算线 (100%)')
            ax2.legend()
            
            # 设置Y轴范围
            ax2.set_ylim(0, max(usage_rates) * 1.2 if usage_rates else 100)
            
            plt.tight_layout()
            
            # 嵌入到界面
            canvas = FigureCanvasTkAgg(fig, self.trend_chart_frame)
            canvas.draw()
            canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)
            
        except Exception as e:
            error_label = tk.Label(self.trend_chart_frame, 
                                text=f"生成趋势图时出错: {str(e)}", 
                                font=("Arial", 12), 
                                foreground="red")
            error_label.pack(pady=20)

    def apply_budget_template(self):
        """应用预算模板"""
        template_name = self.template_var.get()
        if template_name not in self.templates:
            messagebox.showwarning("警告", "请选择有效的模板")
            return
        
        template = self.templates[template_name]
        for category, amount in template.items():
            self.db.set_budget(category, amount, 'monthly')
        
        messagebox.showinfo("成功", f"已应用 {template_name} 模板")
        self.refresh_budgets()

    def save_current_as_template(self):
        """保存当前设置为模板"""
        template_name = self.custom_template_name.get().strip()
        if not template_name:
            messagebox.showwarning("警告", "请输入模板名称")
            return
        
        # 获取当前所有预算
        budgets = self.db.get_budgets('monthly')
        template = {budget['main_category']: budget['amount'] for budget in budgets}
        
        # 保存模板
        self.save_template_to_file(template_name, template)
        messagebox.showinfo("成功", f"已保存模板: {template_name}")
        
        # 更新模板选择框
        self.templates[template_name] = template
        # 这里需要更新UI中的模板选择框，但需要获取到combobox控件
        # 在实际实现中，可能需要重新设置combobox的values

    def save_template_to_file(self, name: str, template: dict):
        """保存模板到文件"""
        import json
        import os
        
        try:
            template_file = 'budget_templates.json'
            
            # 尝试读取现有模板
            if os.path.exists(template_file):
                with open(template_file, 'r', encoding='utf-8') as f:
                    templates = json.load(f)
            else:
                templates = {}
            
            # 添加新模板
            templates[name] = template
            
            # 保存回文件
            with open(template_file, 'w', encoding='utf-8') as f:
                json.dump(templates, f, ensure_ascii=False, indent=2)
                
        except Exception as e:
            print(f"保存模板失败: {e}")
            # 如果文件操作失败，至少保存在内存中
            self.templates[name] = template

    def load_templates_from_file(self):
        """从文件加载模板"""
        import json
        import os
        
        try:
            template_file = 'budget_templates.json'
            if os.path.exists(template_file):
                with open(template_file, 'r', encoding='utf-8') as f:
                    custom_templates = json.load(f)
                    self.templates.update(custom_templates)
        except Exception as e:
            print(f"加载模板失败: {e}")

    def set_budget(self):
        """设置预算"""
        try:
            category = self.budget_category.get()
            amount_str = self.budget_amount.get()
            
            if not category:
                messagebox.showerror("错误", "请选择分类")
                return
            
            try:
                amount = float(amount_str)
            except ValueError:
                messagebox.showerror("错误", "请输入有效的金额")
                return

            if amount <= 0:
                messagebox.showerror("错误", "预算金额必须大于0")
                return
            
            self.db.set_budget(category, amount, 'monthly')
            messagebox.showinfo("成功", f"{category}的月度预算已设置为{amount}元")
            self.budget_amount.set("")
            self.refresh_budgets()
            
        except Exception as e:
            messagebox.showerror("错误", f"设置预算失败: {str(e)}")

    def refresh_budgets(self):
        """刷新预算显示"""
        # 清空现有数据
        for item in self.budget_tree.get_children():
            self.budget_tree.delete(item)
        
        # 获取当前年月
        now = datetime.datetime.now()
        year = now.year
        month = now.month
        
        # 获取预算执行情况
        budget_status = self.db.get_budget_status(year, month)
        
        # 添加数据到表格
        for status in budget_status:
            if status['budget'] > 0:  # 只显示设置了预算的分类
                values = (
                    status['category'],
                    f"{status['budget']:.2f}",
                    f"{status['actual']:.2f}",
                    f"{status['remaining']:.2f}",
                    f"{status['usage_rate']:.1f}%"
                )
                
                item_id = self.budget_tree.insert("", "end", values=values)
                
                # 如果超预算，标记为红色
                if status['is_over_budget']:
                    self.budget_tree.item(item_id, tags=('over_budget',))
            
            # 设置标签样式
            self.budget_tree.tag_configure('over_budget', foreground='red')